/*!
 * \file set_relation_isl_visitor.cc
 *
 * \brief implementation of the SetRelationISLVisitor
 *
 * \date Started: 7/6/2010
 * \date Last Modified: 7/6/2010
 * \authors Alan LaMielle Nicholas Jeanette
 *
 * Copyright (c) 2010, Colorado State University <br>
 * All rights reserved. <br>
 * See ../../COPYING for details. <br>
 */

#include <iegenlib/iegenlib.h>

#include <sstream>
#include <iostream>

using std::string;
using std::cout;
using std::stringstream;

namespace iegenlib{

SetRelationISLVisitor::SetRelationISLVisitor(){
   firstTup = true;
   firstConj = false;
}

void SetRelationISLVisitor::defaultOut(){}

void SetRelationISLVisitor::defaultIn(){}

void SetRelationISLVisitor::SetIn(const Set* x){
   const set<string> symbs = x->GetContext().getSymbolicNames();
   if(symbs.begin() != symbs.end()){
      out +="[";
      for(set<string>::const_iterator itr = symbs.begin(); itr != symbs.end(); itr++){
          out += (*itr);
          out += ",";
      }
      out = out.substr(0, out.size()-1);
      out += "]->";
   }
   out += "{";
   oA = -1;
   iA = 0;
   arityCounter = 0;
}

void SetRelationISLVisitor::SetOut(const Set* x){
      out += "}";
}

void SetRelationISLVisitor::RelationIn(const Relation* x){
   const set<string> symbs = x->GetContext().getSymbolicNames();
   if(symbs.begin() != symbs.end()){
      out +="[";
      for(set<string>::const_iterator itr = symbs.begin(); itr != symbs.end(); itr++){
          out += (*itr);
          out += ",";
      }
      out = out.substr(0, out.size()-1);
      out += "]->";
   }
   out += "{";
   oA = x->getOutArity();
   iA = x->getInArity();
   arityCounter = 0;
}


void SetRelationISLVisitor::RelationOut(const Relation* x){
   out += "}";
}

void SetRelationISLVisitor::SymbolTableIn(SymbolTable* x){
      ST = x;
}

void SetRelationISLVisitor::SRConjunctionCase(const SRConjunction* conj){
   if(firstConj){
      out += "; ";
      firstTup = true;
      arityCounter = 0;
   }
   firstConj = true;
   bool first = true;
   out += "[";
   if(iA == 0 && oA == 0){
      out += "]->[";
   }
   conj->applyTuples(this);
   if(iA > 0 && oA == 0){
     out += "]->[";
   }
   out += "]";

   set<string> exists(this->ST->existNamesBegin(),this->ST->existNamesEnd());
   set<SREquality> equalities(conj->equalitiesBegin(),conj->equalitiesEnd());
   set<SRInequality> inequalities(conj->inequalitiesBegin(),conj->inequalitiesEnd());

   bool contains_exists=exists.size()>0;
   if(contains_exists and (equalities.size()>0 or inequalities.size()>0)){
     out += " : exists(";
     for(set<string>::const_iterator exist_name=exists.begin();
         exist_name!=exists.end(); ++exist_name){
       out+=(*exist_name)+",";
     }
     out=string(out.begin(),out.end()-1);
     out+=" : ";
   }

   for(set<SREquality>::const_iterator itr = equalities.begin();
         itr != equalities.end();
            ++itr)
   {
      if(!first){
         out += " and ";
      }
      else if(!contains_exists){
        out += " : ";
      }
      first = false;
      itr->apply(this);
   }

   for(set<SRInequality>::const_iterator itr = inequalities.begin();
         itr != inequalities.end();
            ++itr)
   {
      if(!first){
         out += " and ";
      }else if(!contains_exists){
         out += " : ";
      }
      first = false;
      itr->apply(this);
   }

   if(contains_exists and (equalities.size()>0 or inequalities.size()>0)){
     out+=")";
   }
}

void SetRelationISLVisitor::SREqualityIn(const SREquality* x){
   ExpVec expr = x->getExpVec();
   out += expr.toString(ST) + "=0";
}

void SetRelationISLVisitor::SRInequalityIn(const SRInequality* x){
   ExpVec expr = x->getExpVec();
   out += expr.toString(ST) + ">=0";
}

void SetRelationISLVisitor::TupleTypeOut(const TupleType* x){
   stringstream ss;
   if(arityCounter == iA && oA != -1 && (iA != 0 || oA != 0)){
      out += "]->[";
      firstTup = true;
   }
   if(x->isConst()){
      ss << x->getValue();
   }else{
      ss << x->getName();
   }
   if(firstTup){
      out += ss.str();
      firstTup = false;
   }else{
      out += "," + ss.str();
   }
   arityCounter++;
}

}//end namespace iegenlib
